/*
 * @Description: 添加水印逻辑
 * @Author: laoyuan MIT License
 * @Date: 2022-01-02 21:46:51
 * @LastEditTime: 2022-01-30 21:57:06
 * @FilePath: \waterMark\src\waterMark.js
 */

var waterMark = (function (exports) {
  'use strict'
  let DIV, canvas, base64URL
    // 水印配置数据
  const defaultConfig = {
    content: 'laoyuan 131xxxxxxxx', // 显示水印的内容, 必传
    canvasWidth: 300, // canvas生成背景图片的宽度, 水印块的宽度， 默认为300
    canvasHeight: 150, // canvas生成背景图片的高度, 水印块的高度，默认为150
    id: 'waterMark', // 显示水印div元素的id
    fontSize: '20px', // 水印字体大小
    fontFamily: '"Microsoft YaHei", SimSun, "sans-serif"', // 字体类型
    textAlign: 'center', // 文本在div种的对齐方式
    textBaseline: 'middle', // 对齐
    fillStyle: 'rgba(120, 220, 200, 0.5)', // 水印文本颜色, 默认为rgba(120, 220, 200, 0.5)
    textRotate: -20, // 文本旋转角度，默认-20, 取值范围-30到30
    imageFormat: 'image/png', // 生成base64图片的格式
    divPosition: 'fixed', // 水印盒子定位方式，默认为固定定位fixed
    divTop: '10px', // 水印盒子顶部定位大小，默认为10px
    divLeft: 0,  // 水印盒子左边定位大小，默认为0
    divRight: 0, // 水印盒子右边定位大小，默认为0
    divBottom: 0, // 水印盒子顶部定位大小，默认为0
    divZindex: 99999, // 水印盒子顶部定位层级，默认为99999
    isGradient: false, // 水印颜色是否使用线性渐变色，默认为false，纯色
    startColor: '#333', // 线性渐变起始颜色，默认为#333
    endColor: '#999' // 线性渐变结束颜色，默认为#999
  }

  /**
   * 创建一个canvas，用来生成水印的base64URL背景图
   */
  function createCanvas (config) {
    if (!canvas) {
      canvas = document.createElement('canvas')
      canvas.width = config.canvasWidth
      canvas.height = config.canvasHeight
      let context = canvas.getContext('2d')
      // 是否创建文本渐变色
      if (config.isGradient) {
        // 创建渐变
        const gradient = context.createLinearGradient(0, 0, canvas.width, 0)
        gradient.addColorStop('0', config.startColor)
        gradient.addColorStop('1.0', config.endColor)
        // 用渐变填色
        context.fillStyle = gradient
      } else {
        // 正常文本纯色
        context.fillStyle = config.fillStyle
      }
      // 文字样式
      context.textAlign = config.textAlign
      context.textBaseline = config.textAlign
      context.font = config.fontSize + config.fontFamily
      // 文本旋转角度计算，
      const radian = config.textRotate * Math.PI / 180
      context.rotate(radian)
      // 填充文本位置处理
      let x = canvas.width / 2 + config.textRotate
      let y = canvas.height - config.textRotate
      // 文本旋转角度大于0时
      if (config.textRotate > 0) {
        x = canvas.width / 2 - config.textRotate
        y = config.textRotate
      }
      // 填充文本
      context.fillText(config.content, x, y, canvas.width)
      // 填充图片
      // context.drawImage(img, 0, 0, canvas.width / 2, canvas.height)
      // 转成base64
      base64URL = canvas.toDataURL(config.imageFormat)
    }
  }

  /**
   * 创建一个div，用来显示水印
   */
  function createDiv (config) {
    if (!DIV) {
      DIV = document.createElement('div')
      DIV.id = config.id
      initSetStyle(config)
      document.body.appendChild(DIV)
    }
  }

  /**
   * 初始化设置创建div的样式
   */
  function initSetStyle (config) {
    DIV.style.position = config.divPosition
    DIV.style.top = config.divTop
    DIV.style.right = config.divRight
    DIV.style.bottom = config.divBottom
    DIV.style.left = config.divLeft
    DIV.style.zIndex = config.divZindex
    DIV.style.background = `url(${base64URL})`
    DIV.style.pointerEvents = 'none'
  }

  /**
   * 监听DOM被操作的执行的处理函数，重新创建水印
   */
  function handleEvent(config) {
    console.log('DIV', DIV)
    if (!DIV) {
      createDiv(config)
    } else {
      // 重新设置样式
      initSetStyle(config)
    }
  }

  /**
   * 监听DOM和style样式被修改的函数，可防止用户用浏览器删除水印
   */
  function observeDOMModified (config) {
    // 监听dom变化
    window.addEventListener('DOMSubtreeModified', function () {
      const waterMark = document.getElementById(defaultConfig.id)
      console.log('waterMark', waterMark)
      if (!waterMark) {
        handleEvent(config)
      }
    })
  
    // 监听style的变化-选择需要观察变动的节点
    const targetNode = document.getElementById(defaultConfig.id)
    // 观察器的配置（需要观察什么变动）
    const observeConfig = { attributes: true, childList: true, subtree: true, attributeFilter: ['style'] }
    const callback = function (mutations) {
      mutations.forEach(function (mutation) {
        if (mutation.type === 'attributes') {
          addEvent(config)
        }
      })
    }
    // 创建一个观察器实例并传入回调函数
    const observer = new MutationObserver(callback)
    // 以上述配置开始观察目标节点
    observer.observe(targetNode, observeConfig)
  }


  // 初始化函数
  exports.init = (opts) => {
    const config = Object.assign(defaultConfig, opts || {})
    createCanvas(config)
    createDiv(config)
    observeDOMModified(config)
  }

  return exports
}({}))

export default waterMark